package com.atguigu.boot_redis01.controller;

import com.atguigu.boot_redis01.utils.RedisUtils;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import redis.clients.jedis.Jedis;

import java.util.Collections;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @author gcq
 * @Create 2020-12-11
 */
@RestController
public class GoodController {

    private String REDIS_LOCK = "atguiguLock";

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Value("${server.port}")
    private String serverPort;

    private String GOODS = "goods:001";

    @Autowired
    private Redisson redisson;

//    @GetMapping("/buy_goods")
//    public String buy_goods() throws Exception {
//
//        String value = UUID.randomUUID().toString() + Thread.currentThread().getName();
//
//        RLock redissonLock = redisson.getLock(REDIS_LOCK);
//        redissonLock.lock();
//        try {
//           /*
//            缺点：设置值和过期时间不是原子性
//            Boolean flag = stringRedisTemplate.opsForValue().setIfAbsent(REDIS_LOCK, value);
//            // 设置10秒后锁自动过期，防止出现意外情况出现死锁
//            stringRedisTemplate.expire(REDIS_LOCK,10, TimeUnit.SECONDS);
//            */
//            // 同时设置过期时间，保证原子性
//         /*   Boolean flag = stringRedisTemplate.opsForValue().setIfAbsent(REDIS_LOCK,value,10L,TimeUnit.SECONDS);
//            if (!flag) {
//                return "抢锁失败";
//            }*/
//            // 取出库存
//            String result = stringRedisTemplate.opsForValue().get(GOODS);
//            int goodsNumber = result == null ? 0 : Integer.parseInt(result);
//
//            // 库存大于0
//            if (goodsNumber > 0) {
//                // 减库存
//                int realNumber = goodsNumber - 1;
//                // 重新设置回去
//                stringRedisTemplate.opsForValue().set(GOODS, String.valueOf(realNumber));
//                System.out.println("成功买到商品，库存还剩下：" + realNumber + "件" + "\t 服务提供端口 " + serverPort);
//                return "成功买到商品，库存还剩下：" + realNumber + "件" + "\t 服务提供端口 " + serverPort;
//            } else {
//                System.out.println("商品已经售完/活动结束/调用超时，欢迎下次光临" + "\t 服务提供端口 " + serverPort);
//            }
//            return "商品已经售完/活动结束/调用超时，欢迎下次光临" + "\t 服务提供端口 " + serverPort;
//        } finally {
//
//            /**直接unlock 在超高并发情况下出现 attempt to unlock lock not locked by current thread by node id，
//             * 不是当前线程解锁
//            redissonLock.unlock();
//             **/
//            // 在锁定状态
//            if (redissonLock.isLocked()) {
//                // 是否是当前线程持有
//                if (redissonLock.isHeldByCurrentThread()) {
//                    redissonLock.unlock();
//                }
//            }
//
//            /** 删锁功能实现：↓ **/
//
//            // 不能删除其他人的锁
////            if (stringRedisTemplate.opsForValue().get(REDIS_LOCK).equals(value)) {
////                stringRedisTemplate.delete(REDIS_LOCK);
////            }
//            /**
//             * 不用lua脚本，你还有其他的想法吗 ?
//             * redis事务
//             */
//           /* while(true) {
//                // 使用redis事务
//                if (stringRedisTemplate.opsForValue().get(REDIS_LOCK).equalsIgnoreCase(value)) {
//                    stringRedisTemplate.setEnableTransactionSupport(true);
//                    stringRedisTemplate.multi();
//                    stringRedisTemplate.delete(REDIS_LOCK);
//                    List<Object> list = stringRedisTemplate.exec();
//                    if (list != null) {
//                        continue;
//                    }
//                }
//                stringRedisTemplate.unwatch();
//                break;
//            }*/
//            /*太过负责*/
//          /*  Jedis jedis = RedisUtils.getJedis();
//
//            String script = "if redis.call('get',KEYS[1]) == ARGV[1] " +
//                    "then " +
//                    "return redis.call('del',KEYS[1]) " +
//                    "else " +
//                    "   return 0 " +
//                    "end";
//            try {
//                // 根据 key,value 加上lua脚本进行删除
//                Object o = jedis.eval(script,
//                        Collections.singletonList(REDIS_LOCK),
//                        Collections.singletonList(value));
//                if ("1".equals(o.toString())) {
//                    System.out.println("------del redis lock ok");
//                } else {
//                    System.out.println("------del redis lock error");
//                }
//            } finally {
//                if (null != jedis) {
//                    jedis.close();
//                }
//            }*/
//        }
//
//    }

    @GetMapping("/buy_goods")
    public String buy_goods() throws Exception {
        String value = UUID.randomUUID().toString()+ Thread.currentThread().getName();

        Boolean flag = stringRedisTemplate.opsForValue().setIfAbsent(REDIS_LOCK, value);

        if (!flag) {
            return "抢锁失败";
        }

        String result = stringRedisTemplate.opsForValue().get(GOODS);

        int goodsNumber = result == null ? 0 : Integer.parseInt(result);

        // 库存大于0
        if (goodsNumber > 0) {
            // 减库存
            int realNumber = goodsNumber - 1;
            // 重新设置回去
            stringRedisTemplate.opsForValue().set(GOODS, String.valueOf(realNumber));
            System.out.println("成功买到商品，库存还剩下：" + realNumber + "件" + "\t 服务提供端口 " + serverPort);
            stringRedisTemplate.delete(REDIS_LOCK);
            return "成功买到商品，库存还剩下：" + realNumber + "件" + "\t 服务提供端口 " + serverPort;
        } else {
            System.out.println("商品已经售完/活动结束/调用超时，欢迎下次光临" + "\t 服务提供端口 " + serverPort);
        }
        return "商品已经售完/活动结束/调用超时，欢迎下次光临" + "\t 服务提供端口 " + serverPort;

    }
}